package com.gyj.user.service.impl;

import com.gyj.user.dao.UserDao;
import com.gyj.user.model.User;
import com.gyj.user.service.TestService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;
import java.util.UUID;

/**
 * Created by Gao on 2018/5/24.
 */
@Service
public class TestServiceImpl implements TestService {

    private Logger logger = LoggerFactory.getLogger(TestServiceImpl.class);

    @Autowired
    private UserDao userDao;

    /**
     * Cacheable标注的方法，Spring在每次执行前都会检查Cache中是否存在相同key的缓存元素，如果存在就不再执行该方法，
     * 而是直接从缓存中获取结果进行返回，否则才会执行并将返回结果存入指定的缓存中
     */
    @Override
    @Cacheable(value = "user")
    public List<User> getAllUserList() {
        List<User> all = userDao.findAll();

        return all;
    }

    /**
     * CachePut标注的方法在执行前不会去检查缓存中是否存在之前执行过的结果，而是每次都会执行该方法，
     * 并将执行结果以键值对的形式存入指定的缓存中
     * 添加应该会用@CacheEvict注解
     */
    @Override
    @CacheEvict(value = "user", allEntries = true)
    public Boolean addUserList() {
        for (int i = 0; i < 10; i++) {
            String sid = UUID.randomUUID().toString();
            String sid1 = UUID.randomUUID().toString();
            User user = new User();
            user.setNickName("明明");
            user.setLoginName("小明");
            user.setPassword(sid);
            user.setCreateTime(new Date());
            User user1 = new User();
            user1.setNickName("小二");
            user1.setLoginName("小红");
            user1.setPassword(sid1);
            user1.setCreateTime(new Date());
            userDao.save(user);
            userDao.save(user1);
        }

        return true; //添加成功此时redis存储的是true
    }

    @Override
    @Cacheable(value = "user", key = "#id")  //@Cacheable(value = "user") //使用自定义的key生成策略
    public User getUserById(String id) {
        User user = userDao.findById(Integer.parseInt(id));

        return user;
    }

    @CacheEvict(value = "user", key = "#id")
    @Override
    public User updateUser(String id, String nickname) {
        User user = userDao.findById(Integer.parseInt(id));
        user.setNickName(nickname);
        userDao.save(user);
        // 返回用户基本信息 用于更新缓存
        User userCache = userDao.findById(Integer.parseInt(id));

        return userCache;
    }

    /**
     * CRUD(Create创建，Retrieve读取，Update更新，Delete删除) 操作中，除了 R 具备幂等性，其他三个发生的时候都可能会造成缓存结果和数据库不一致。
     * 为了保证缓存数据的一致性，在进行 CUD 操作的时候我们需要对可能影响到的缓存进行更新或者清除。
     * @param id
     */
    //删除缓存名字为findOne下的所有的缓存数据
    @CacheEvict(value = "user", key = "#id")
    @Override
    public User updateUserById(String id) {
        User user = userDao.findById(Integer.parseInt(id));
        user.setNickName("66666");
        user.setLoginName("6666");
        user.setPassword("vf dv v");
        userDao.save(user);
        // 返回用户基本信息 用于更新缓存
        User userCache = userDao.findById(Integer.parseInt(id));

        return userCache;
    }

    /**
     * CacheEvict是用来标注在需要清除缓存元素的方法或类上的。当标记在一个类上时表示其中所有的方法的执行都会触发缓存的清除操作。
     * CacheEvict可以指定的属性有value、key、condition、allEntries和beforeInvocation。其中value、key和condition的语义与Cacheable对应的属性类似。
     * 即value表示清除操作是发生在哪些Cache上的（对应Cache的名称）；key表示需要清除的是哪个key，如未指定则会使用默认策略生成的key；
     * condition表示清除操作发生的条件。
     *
     * allEntries是boolean类型，表示是否需要清除缓存中的所有元素。默认为false，表示不需要。当指定了allEntries为true时，Spring Cache将忽略指定的key。
     * 有的时候我们需要Cache一下清除所有的元素，这比一个一个清除元素更有效率。
     *
     * 清除操作默认是在对应方法成功执行之后触发的，即方法如果因为抛出异常而未能成功返回时也不会触发清除操作。使用beforeInvocation可以改变触发清除操作的时间，
     * 当我们指定该属性值为true时，Spring会在调用该方法之前清除缓存中的指定元素
     */
    @CacheEvict(value = "user", key = "#id") //根据id删除缓存
    @Override
    public void deleteUserById(String id) {
        userDao.deleteById(Integer.parseInt(id));
    }

}
